package com.jdzy.student.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jdzy.common.constants.CommonConstants;
import com.jdzy.common.constants.ThesisConstants;
import com.jdzy.model.common.dtos.PageRequestDto;
import com.jdzy.model.common.vos.PageResult;
import com.jdzy.model.common.vos.Result;
import com.jdzy.model.student.dtos.ThesisDeleteDto;
import com.jdzy.model.student.dtos.ThesisDto;
import com.jdzy.model.student.dtos.ThesisSearchDto;
import com.jdzy.model.student.pojos.Thesis;
import com.jdzy.model.student.pojos.ThesisParticipant;
import com.jdzy.model.student.vos.ThesisVo;
import com.jdzy.student.mapper.ThesisMapper;
import com.jdzy.student.mapper.ThesisParticipantMapper;
import com.jdzy.student.service.ThesisService;
import com.jdzy.utils.common.ParseToListOrStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class ThesisServiceImpl extends ServiceImpl<ThesisMapper, Thesis> implements ThesisService {

    @Autowired
    private ThesisMapper thesisMapper;

    @Autowired
    private ThesisParticipantMapper thesisParticipantMapper;

    /**
     * 根据学号获取论文信息
     *
     * @param stuId
     * @param page
     * @param size
     * @return
     */
    @Override
    public Result getThesisByUserId(String stuId, Integer page, Integer size, ThesisSearchDto thesisSearchDto) {
        //1、检查参数
        if(StringUtils.isBlank(stuId)){
            return Result.error(CommonConstants.PARAM_REQUIRE);
        }
        //设置分页
        PageRequestDto pageRequestDto=new PageRequestDto(page,size);
        pageRequestDto.checkParam();
        //分页查询
        IPage iPage=new Page(pageRequestDto.getPage(),pageRequestDto.getSize());

        //2、进行查询参数
        LambdaQueryWrapper<Thesis> thesisLambdaQueryWrapper = Wrappers.<Thesis>lambdaQuery()
                .eq(Thesis::getStuId, stuId)
                .eq(thesisSearchDto.getThesisLevel()!=null, Thesis::getThesisLevel, thesisSearchDto.getThesisLevel())
                .like(StringUtils.isNotBlank(thesisSearchDto.getThesisName()), Thesis::getThesisName, thesisSearchDto.getThesisName())
                .eq(thesisSearchDto.getThesisStatus() != null, Thesis::getThesisStatus, thesisSearchDto.getThesisStatus())
                .ge(thesisSearchDto.getThesisStartTime() != null, Thesis::getThesisStartTime, thesisSearchDto.getThesisStartTime())
                .le(thesisSearchDto.getThesisEndTime() != null, Thesis::getThesisEndTime, thesisSearchDto.getThesisEndTime());
        //2.1、对于参与人进行查询(这里是精确查找)
        //2.1.1、看条件参数是否为空嘛
        String thesisParticipantStr = thesisSearchDto.getThesisParticipantStr();
        if(StringUtils.isNotBlank(thesisParticipantStr)){
            //不为空向数据库寻找
            List<String> thesisParticipantNames = ParseToListOrStringUtils
                    .parseToListWithString(thesisParticipantStr,ThesisConstants.THESIS_PARTICIPANT_SPILT);
            List<Long> thesisId = thesisParticipantMapper.getThesisIdListByName(stuId,thesisParticipantNames);
            if(thesisId!=null || thesisId.size()==0){
                //此时为空参与人  则直接就返回空值
                return Result.success();
            }
            thesisLambdaQueryWrapper.in(Thesis::getId,thesisId);
        }
        IPage selectPage = thesisMapper.selectPage(iPage, thesisLambdaQueryWrapper);

        List<Thesis> thesisList = selectPage.getRecords();
        //3.1、封装参数
        List<ThesisVo> thesisVos=new ArrayList<>();
        for (Thesis thesis : thesisList) {
            // 3.2、查询thesisParticipant表
            List<String> thesisParticipantNameList=thesisParticipantMapper.getParticipantNameList(thesis.getId());
            ThesisVo thesisVo=new ThesisVo();
            BeanUtils.copyProperties(thesis,thesisVo);

            /*
             和前端交流  这里变成字符串返回
             */

            thesisVo.setThesisParticipantStr(ParseToListOrStringUtils
                    .parseToString(thesisParticipantNameList,ThesisConstants.THESIS_PARTICIPANT_SPILT));

            thesisVos.add(thesisVo);
        }
        //3、封装分页数据
        PageResult pageResult=new PageResult(pageRequestDto.getPage(),pageRequestDto.getSize(),iPage.getTotal());
        pageResult.setData(thesisVos);
        return pageResult;
    }

    /**
     * 删除论文信息
     * @param stuId
     * @param thesisDeleteDto
     * @return
     */
    @Override
    public Result deleteThesis(String stuId, ThesisDeleteDto thesisDeleteDto) {
        //1、检查参数
        if(StringUtils.isBlank(stuId) || thesisDeleteDto==null || thesisDeleteDto.getThesisIds().isEmpty()){
            return Result.error(CommonConstants.PARAM_REQUIRE);
        }

        synchronized ("deleteThesis"+CommonConstants.LOCK_INDEX+stuId){
            //2、进行操作thesis表
            thesisMapper.delete(Wrappers.<Thesis>lambdaQuery()
                    .eq(Thesis::getStuId, stuId)
                    .in(Thesis::getId, thesisDeleteDto.getThesisIds()));
            //3、进行操作thesisParticipant表
            thesisParticipantMapper.delete(Wrappers.<ThesisParticipant>lambdaQuery()
                    .in(ThesisParticipant::getThesisId,thesisDeleteDto.getThesisIds()));
        }

        return Result.success();
    }

    /**
     * 新增论文信息
     * @param thesisDto
     * @return
     */
    @Override
    public Result saveThesis(ThesisDto thesisDto) {
        //1、检查参数
        if(thesisDto==null || StringUtils.isBlank(thesisDto.getStuId())){
            return Result.error(CommonConstants.PARAM_REQUIRE);
        }
        //2、进行参数拷贝
        Thesis thesis=new Thesis();
        BeanUtils.copyProperties(thesisDto,thesis);
        //3、保存到thesis表中
        int insert = thesisMapper.insert(thesis);
        if(insert==0){
            return Result.error(CommonConstants.INSERT_FAIL);
        }
        //4、开始操作thesisParticipant表中

        /*
         和前端讨论  以字符串形式 传递  传递到thesisParticipantStr属性中  规定以","分割
         */

        thesisDto.setThesisParticipants(ParseToListOrStringUtils
                .parseToListWithString(thesisDto.getThesisParticipantStr(),ThesisConstants.THESIS_PARTICIPANT_SPILT));

        List<String> thesisParticipants = thesisDto.getThesisParticipants();
        for (String thesisParticipantName : thesisParticipants) {
            ThesisParticipant thesisParticipant=new ThesisParticipant();
            thesisParticipant.setThesisId(thesis.getId());
            thesisParticipant.setStuId(thesis.getStuId());
            thesisParticipant.setThesisParticipantName(thesisParticipantName);
            thesisParticipantMapper.insert(thesisParticipant);
        }
        return Result.success();
    }

    /**
     * 修改论文信息
     * @param thesisDto
     * @return
     */
    @Override
    public Result updateThesis(ThesisDto thesisDto) {
        //1、检查参数
        if(thesisDto==null || StringUtils.isBlank(thesisDto.getStuId()) ||thesisDto.getId()==null){
            return Result.error(CommonConstants.PARAM_REQUIRE);
        }
        synchronized ("updateThesis"+CommonConstants.LOCK_INDEX+thesisDto.getStuId()
                +CommonConstants.LOCK_INDEX+thesisDto.getId()){
            //2、检查数据库中有无该条数据
            Thesis thesis = thesisMapper.selectOne(Wrappers.<Thesis>lambdaQuery()
                    .eq(Thesis::getStuId, thesisDto.getStuId())
                    .eq(Thesis::getId, thesisDto.getId()));
            if(thesis==null){
                return Result.error(CommonConstants.DATASOURCE_IS_NULL);
            }
            //3、拷贝数据,开始修改Theis表
            BeanUtils.copyProperties(thesisDto,thesis);
            int updateThesis = thesisMapper.updateById(thesis);
            if(updateThesis==0){
                return Result.error(CommonConstants.UPDATE_FAIL);
            }
            //4、修改成功  修改ThesisParticipant
            //4.1、先从ThesisParticipant中获取老旧的名称
            List<String> oldThesisParticipantNames = thesisParticipantMapper.getParticipantNameList(thesisDto.getId());
            //以防有重名人  用Map进行统计
            Map<String,Integer> oldThesisParticipantNameMap=new HashMap<>();
            for (String oldThesisParticipantName : oldThesisParticipantNames) {
                oldThesisParticipantNameMap.put(oldThesisParticipantName,oldThesisParticipantNameMap
                        .getOrDefault(oldThesisParticipantName,0)+1);
            }

            //4、3同样将传入的数据进行转换成Map
            /*
            这里和前端商议好了 字符串传递  并商议好 "," 为分割
             */

            thesisDto.setThesisParticipants(ParseToListOrStringUtils.parseToListWithString(thesisDto
                    .getThesisParticipantStr(),ThesisConstants.THESIS_PARTICIPANT_SPILT));

            List<String> newThesisParticipantNames = thesisDto.getThesisParticipants();

            Map<String,Integer> newThesisParticipantNameMap=new HashMap<>();
            for (String newThesisParticipantName : newThesisParticipantNames) {
                newThesisParticipantNameMap.put(newThesisParticipantName,newThesisParticipantNameMap
                        .getOrDefault(newThesisParticipantName,0)+1);
            }
            //4、4  比较两个Map是否相等
            if(oldThesisParticipantNameMap.equals(newThesisParticipantNameMap)){
                return Result.success();
            }else{
                //4.5、不一样   图方便全部删除
                thesisParticipantMapper.delete(Wrappers.<ThesisParticipant>lambdaQuery()
                        .eq(ThesisParticipant::getThesisId,thesisDto.getId()));
                //开始插入新数据
                if(thesisDto.getThesisParticipants().size()==0){
                    return Result.success();
                }else{
                    List<String> thesisParticipantNames = thesisDto.getThesisParticipants();
                    for (String thesisParticipantName : thesisParticipantNames) {
                        ThesisParticipant thesisParticipant=new ThesisParticipant();
                        thesisParticipant.setThesisId(thesisDto.getId());
                        thesisParticipant.setStuId(thesisDto.getStuId());
                        thesisParticipant.setThesisParticipantName(thesisParticipantName);
                        thesisParticipantMapper.insert(thesisParticipant);
                    }
                }
            }
            return Result.success();
        }


    }
}
